---
description: Updating to Hasura GraphQL Engine v2
keywords:
  - hasura
  - docs
  - guide
  - compatibility
  - update v2
sidebar_position: 3
sidebar_label: Updating to Hasura v2
---

import GraphiQLIDE from '@site/src/components/GraphiQLIDE';

# Updating to Hasura GraphQL Engine v2

## Introduction

This page talks about the conceptual changes introduces in Hasura v2 and things to keep in mind while updating from
Hasura v1 to v2.

Do reach out to us if you run into any issues while using Hasura v2 or have any questions regarding any changes
introduced.

## What has changed?

### Concepts

The following are the most significant conceptual changes introduced in Hasura v2:

- Hasura v2 can now connect to multiple databases to generate a unified GraphQL API. Each connected database will have a
  unique "source name" that is used to identify it. Apart from Postgres, connecting to SQL server databases is also now
  supported.
- Config for connecting a database used to be a startup configuration (i.e. set via env vars/flags) but since v2, it is
  a part of Hasura Metadata and can be managed dynamically. See [connecting databases](/databases/overview.mdx).
- Hasura Metadata can now be stored in a separate dedicated Postgres DB.

:::info Note

A detailed changelog with all the new features introduced in Hasura v2 is available on the
[releases page](https://github.com/hasura/graphql-engine/releases).

:::

### Breaking behavior changes {#hasura-v2-behavior-changes}

<div id="hasura-v2-null-where-change" />

- **Semantics of explicit "null" values in "where" filters have changed**

  According to the discussion in
  [this GitHub issue](https://github.com/hasura/graphql-engine/issues/704#issuecomment-635571407), an explicit `null`
  value in a comparison input object will be treated as an error rather than resulting in the expression being evaluated
  to `True`.

  For example: The mutation `delete_users(where: {id: {_eq: $userId}}) { name }` will yield an error if `$userId` is
  `null` instead of deleting all users.

  The older behavior can be preserved by setting the `HASURA_GRAPHQL_V1_BOOLEAN_NULL_COLLAPSE` env var to `true`.

- **Semantics of "null" join values in Remote Schema relationships have changed**

  In a Remote Schema relationship query, the Remote Schema will be queried when all of the joining arguments are not
  `null` values. When there are `null` value(s), the Remote Schema won't be queried and the response of the remote
  relationship field will be `null`. Earlier, the Remote Schema was queried with the `null` value arguments and the
  response depended upon how the Remote Schema handled the `null` arguments but as per user feedback, this behavior was
  clearly not expected.

- **Order of keys in objects passed as "order_by" operator inputs is not preserved**

  The `order_by` operator accepts an array of objects as input to allow ordering by multiple fields in a given order,
  i.e. `[{field1: sortOrder}, {field2: sortOrder}]` but it is also accepts a single object with multiple keys as an
  input, i.e. `{field1: sortOrder, field2: sortOrder}`. In earlier versions, Hasura's query parsing logic used to
  maintain the order of keys in the input object and hence the appropriate `order by` clauses with the fields in the
  right order were generated.

  As the [GraphQL spec](http://spec.graphql.org/June2018/#sec-Input-Object-Values) specifies that input object keys are
  unordered, Hasura v2.0's new and stricter query parsing logic doesn't maintain the order of keys in the input object,
  removing the previous guarantee that the generated `order by` clauses specify the fields in the given order.

  For example: The query `fetch_users(order_by: {age: desc, name: asc}) {id name age}` which is intended to fetch users
  ordered by their age and then by their name is now not guaranteed to return results first ordered by age and then by
  their name as the `order_by` input is passed as an object. To achieve the expected behavior, the query
  `fetch_users(order_by: [{age: desc}, {name: asc}]) {id name age}` should be used, which uses an array to define the
  order of fields to generate the appropriate `order by` clause.

  This has an effect on query operators that depend on `order_by`, most notably `distinct_on`. The `distinct_on`
  operator relies on the order of `order_by`, and therefore is also impacted by this change.

  To avoid confusion and potentially-unwanted behavior, you should use an array value for all `order_by` clauses.

- **Type name for computed fields' input argument has changed**

  The name of the computed field input argument has changed from `<function_name>_args` to
  `<computed_field_name>_<table_name>_args`. This change enables adding a root-level tracked function as a computed
  field which previously would have thrown an input type conflict error.

- **Hasura APIs generated by older Hasura versions cannot be added as Remote Schemas to Hasura v2**

  With v2.0, some of the auto-generated schema types have been extended. For example, `String_comparison_exp` has an
  additional `regex` input object field. This means if you have a Hasura API with an older Hasura version added as a
  Remote Schema then it will have a type conflict. You should update all Hasura Remote Schemas to avoid such type
  conflicts.

- **CLI Migrations are executed sequentially, instead of one large transaction**

  While applying multiple Migrations, in earlier Hasura CLI versions all migration files were run under one transaction
  block. i.e. if any migration threw an error, all the previously successfully executed Migrations would be rolled back.
  With Hasura CLI v2.0, each migration file is run in its own transaction block but all the Migrations are not executed
  under one. i.e. if any migration throws an error, applying further Migrations will be stopped but the other
  successfully executed Migrations up till that point will not be rolled back.

- **Passing extra GQL params will now throw validation error**

  According to the discussion in
  [this GitHub issue](https://github.com/hasura/graphql-engine/issues/9320#issue-1503972127), passing unused, required
  GQL params will now throw a validation error.

  Per the [GraphQL spec](https://spec.graphql.org/June2018/#sec-All-Variables-Used), any variable - if defined by an
  operation as required - should be referenced/used in the operation.

  In the example below, the `role_type` variable is defined but not referenced or used in operation. Thus, executing
  this query will result in a validation error.

<GraphiQLIDE
  query={`query fetch_users($role_type: String!) { 
  users { 
    displayName 
    id 
    role 
    } 
}`}
  variables={`{ "role_type": "user" }`}
  response={`{
  "errors": [
    {
      "extensions": {
        "code": "validation-failed",
        "path": "$"
      },
      "message": "unexpected variables in variableValues: role_type"
    }
  ]
}`}
/>

<div id="hasura-v2-env-changes" />

- **Deprecation of database specific env vars**

  In v2.0, the values of the following env vars are used to define the connection parameters of the `default` database
  while updating an existing instance or while starting a fresh instance. During Metadata initialization, their values
  are moved to the Metadata of the `default` database as defined [here](/api-reference/syntax-defs.mdx#pgconfiguration).

  - `HASURA_GRAPHQL_PG_CONNECTIONS`
  - `HASURA_GRAPHQL_PG_TIMEOUT`
  - `HASURA_GRAPHQL_NO_OF_RETRIES`
  - `HASURA_GRAPHQL_PG_POOL_TIMEOUT`
  - `HASURA_GRAPHQL_USE_PREPARED_STATEMENTS`
  - `HASURA_GRAPHQL_TX_ISOLATION`
  - `HASURA_GRAPHQL_READ_REPLICA_URLS`
  - `HASURA_GRAPHQL_CONNECTIONS_PER_READ_REPLICA`

  **Post the initial setup/update once the Metadata is initialized, these env vars can be considered as Deprecated.**
  i.e. Changing or setting values of these env vars will have no impact as the values in the Hasura Metadata are now
  used to define the connection parameters.

### Hasura configuration {#hasura-v2-config-changes}

- To accommodate changes for storing information for multiple databases, the Hasura Metadata and the Hasura CLI project
  versions have been bumped from `v2` to `v3`. The `v2` versions of the Metadata and CLI project can continue to be used
  with Hasura v2 instances. Hasura v2 will assume the `v2` Metadata and Migrations belong to a database connected with
  the name `default`.

- A new mandatory env var `HASURA_GRAPHQL_METADATA_DATABASE_URL` is now introduced and is mandatory for storing Hasura
  Metadata.

- Custom env vars can now be used to connect databases dynamically at runtime.

- With support for multiple databases, older database specific env vars have been deprecated.
  [See details](#hasura-v2-env-changes)

:::info Existing Metadata

`HASURA_GRAPHQL_METADATA_DATABASE_URL` must be the connection string for where your metadata existed previously.

:::

## Moving from Hasura v1 to Hasura v2 {#moving-from-hasura-v1-to-v2}

### Hasura v1 and Hasura v2 compatibility {#hasura-v1-v2-compatibility}

All existing Metadata and Migrations from a Hasura v1 instance are assumed to belong to a database named `default` in
Hasura v2.

Hence **in Hasura v2, a database with name "default" needs to be added to apply Metadata and Migrations from a Hasura v1
instance**.

Post adding a database named `default`, the Hasura v2 instance should behave equivalently to the Hasura v1 instance and
all previous workflows will continue working as they were.

Refer to [connecting databases](/databases/quickstart.mdx) to add a database to Hasura v2.

### Migrate Hasura v1 instance to Hasura v2

Hasura v2 is backwards compatible with Hasura v1. Hence simply updating the Hasura docker image version number and
restarting your Hasura instance should work seamlessly.

:::info Note

In case you happen to have a large number of past cron and Event Trigger logs in your database, this might slow down the
update to v2 and might even cause unexpected errors in certain scenarios.

**It is highly recommended to clean up past cron and Event Trigger logs data from the database before attempting the
update if you have a lot of historical data.**

You can take a dump of this data before cleaning up if you wish to keep the log history. This data can be restored back
into the DB if required post the update.

:::

## Post update steps {#hasura-v1-to-v2-post-update-steps}

### Remove deprecated ENV Vars

With support for multiple databases, database connection related config is now stored in Hasura Metadata and the older
database specific env vars have been deprecated. [See details](#hasura-v2-env-changes).

Post update to Hasura v2 these env vars can be removed as they will now be ignored.

This config can now be modified by updating the Hasura Metadata for the connected database(s) via the Console/CLI/APIs.

### Upgrade CLI project to enable multiple database and other new features support

Update your Hasura CLI project to `config v3` using the steps mentioned in
[this guide](/migrations-metadata-seeds/legacy-configs/upgrade-v3.mdx) to take full advantages of the features
introduced in Hasura v2.

Post upgrading to `config v3`, the database connection parameters would have been moved to the metadata. Hence it is
important to ensure that the same env vars are used for storing database connection strings across all environments and
the Metadata being applied also uses the appropriate env vars.

:::info Note

If you do not need multiple database support or any of new features introduced in Hasura v2, like REST endpoints,
inherited roles etc., then you can continue to use `config v2` project directory and workflows.

Though we would recommend to upgrade to `config v3` anyway as it includes some useful directory structure changes.

:::

### Updates to CI/CD after updating to Hasura v2

The following commands need to be executed in the specified order to apply Metadata and Migrations in CI/CD workflows

- If using Hasura CLI project in `config v2`:
  - No changes needed.
  - Run:
    - `hasura migrate apply` - _(apply migrations to the database named "default")_
    - `hasura metadata apply` - _(apply metadata to the database named "default")_
- If using Hasura CLI project in `config v3`:
  - Ensure that the same env vars are used for storing database connection strings across all environments and the
    Metadata being applied also uses the appropriate env vars.
  - Run:
    - `hasura metadata apply` - _(connect Hasura to the databases configured in the metadata)_
    - `hasura migrate apply --all-databases` - _(apply the migrations to the connected databases)_
    - `hasura metadata reload` - _(make Hasura aware of any newly created database objects in the previous step)_

## Downgrading back to Hasura v1

In case there are some issues with your Hasura instance post updating to Hasura v2, you can downgrade back to Hasura v1
by reverting the Hasura docker image version and using the [downgrade command](/deployment/downgrading.mdx) to revert
the Hasura Metadata catalogue changes:

```bash
docker run -e HASURA_METADATA_DATABASE_URL=$POSTGRES_URL hasura/graphql-engine:v2.0.0 graphql-engine downgrade --to-v1.3.3
```

:::info Note

You can downgrade a Hasura v2 instance to Hasura v1 only if there is only one database connected to it.

:::
